package com.example.matchingengine.service.strategy;

import com.example.matchingengine.model.Order;
import com.example.matchingengine.model.Order.OrderStatus;
import com.example.matchingengine.service.model.OrderBook;
import lombok.extern.slf4j.Slf4j;

import java.math.BigDecimal;

/**
 * 抽象匹配模板类
 * 定义订单匹配的模板方法，具体匹配逻辑由子类实现
 * 同时实现原型模式，支持策略对象的克隆复用
 */
@Slf4j
public abstract class AbstractMatchingTemplate implements MatchingStrategy, PrototypeStrategy {
    
    @Override
    public final void match(Order order, OrderBook orderBook) {
        // 模板方法：定义匹配流程
        log.info("开始匹配订单: {}, 类型: {}, 方向: {}", order.getId(), order.getType(), order.getSide());
        
        // 1. 前置检查
        if (!preCheck(order)) {
            log.warn("订单前置检查失败: {}", order.getId());
            return;
        }
        
        // 2. 执行具体的匹配逻辑（由子类实现）
        doMatch(order, orderBook);
        
        // 3. 后置处理
        postProcess(order, orderBook);
        
        log.info("订单匹配完成: {}, 最终状态: {}", order.getId(), order.getStatus());
    }
    
    /**
     * 前置检查（钩子方法，子类可以重写）
     * @param order 订单
     * @return 是否通过检查
     */
    protected boolean preCheck(Order order) {
        // 检查订单状态
        if (order.getStatus() == OrderStatus.CANCELED) {
            log.info("订单已取消，不进行撮合: {}", order.getId());
            return false;
        }
        
        // 检查订单数量
        if (order.getQuantity().compareTo(BigDecimal.ZERO) <= 0) {
            log.warn("订单数量无效: {}, 数量: {}", order.getId(), order.getQuantity());
            return false;
        }
        
        return true;
    }
    
    /**
     * 执行具体的匹配逻辑（抽象方法，由子类实现）
     * @param order 订单
     * @param orderBook 订单簿
     */
    protected abstract void doMatch(Order order, OrderBook orderBook);
    
    /**
     * 后置处理钩子方法
     * 子类可以重写此方法进行后置处理
     * @param order 订单
     * @param orderBook 订单簿
     */
    protected void postProcess(Order order, OrderBook orderBook) {
        // 默认空实现，子类可以重写
        log.debug("订单 {} 匹配完成后置处理", order.getId());
    }
    
    /**
     * 克隆策略对象
     * @return 克隆的策略对象
     */
    @Override
    public PrototypeStrategy clone() {
        try {
            return (PrototypeStrategy) super.clone();
        } catch (CloneNotSupportedException e) {
            log.error("策略克隆失败: {}", e.getMessage(), e);
            throw new RuntimeException("策略克隆失败", e);
        }
    }
    
    /**
     * 重置策略状态
     * 在复用策略对象时，需要重置内部状态
     */
    @Override
    public void reset() {
        // 默认空实现，子类可以重写进行状态重置
        log.debug("重置策略状态: {}", getStrategyType());
    }
}